<template>
    <div class="form-group">
        <label v-if="label">{{ label }}</label>
        <multiselect
            :id="'category-select-' + _uid"
            v-model="content"
            track-by="id"
            label="fullname"
            group-values="items"
            group-label="type"
            :class="{'border border-danger':error}"
            :loading="loading"
            :placeholder="$t('type here to search')"
            :options="options"
            :multiple="multiple"
            :show-labels="false"
            :searchable="true"
            :internal-search="false"
            @open="load(null)"
            @input="updateSeletected"
            @search-change="load">

            <template slot="noResult">
                <slot name="noResult">{{ $t("No elements found. Consider changing the search query.") }}</slot>
            </template>
            <template slot="noOptions">
                <slot name="noOptions">{{ $t("No Data Available") }}</slot>
            </template>
        </multiselect>

        <small v-if="error" class="text-danger">{{ error }}</small>
        <small v-if="helper" class="form-text text-muted">{{ $t(helper) }}</small>

    </div>

</template>

<script>
  export default {
    props: {
      value: null,
      label: {
        type: String,
        default: ""
      },
      multiple: {
        type: Boolean,
        default: true
      },
      hideUsers: {
        type: Boolean,
        default: false
      },
      hideGroups: {
        type: Boolean,
        default: false
      },
      error: String,
      helper: String,
    },
    data () {
      return {
        loading: false,
        selected: {
          users: [],
          groups: []
        },
        options: [],
        results: [],
        lastEmitted: "",
        labelUsers: this.$t("Users"),
        labelGroups: this.$t("Groups"),
      };
    },
    computed: {
      content: {
        get () {
          if (this.loading) {
            return [];
          }
          return this.selected.users.map(user => {
            let uid;
            if (typeof user === 'number') {
              uid = user;
            } else {
              uid = user.id;
            }
            return this.results.find(item => item.id === uid);
          })
            .concat(this.selected.groups.map(group => {
              let gid;
              if (typeof group == 'number') {
                gid = "group-" + group;
              } else {
                gid = group.id;
              }
              return this.results.find(item => item.id ===  gid);
              
            }));
        },
        set (value) {
          this.selected.users = [];
          this.selected.groups = [];
          if (value === null) {
            return;
          }

          // If it is array (this happens when the Select User/Group is selected)
          // add value just if it is not empty
          if (Array.isArray(value) && value.length) {
            value.forEach(item => {
              this.results.push(item);
              if (typeof item.id === "number") {
                this.selected.users.push(item.id);
              } else {
                this.selected.groups.push(parseInt(item.id.substr(6)));
              }
            });
          }

          //If an object arrives as value (this happens with Self Service and assign by expression)
          if (!Array.isArray(value) && value)
          {
            this.results.push(value);
            if (typeof value.id === "number") {
              this.selected.users.push(value);
            } else {
              this.selected.groups.push(value);
            }
          }

        }
      }
    },
    watch: {
      value: {
        immediate: true,
        deep: true,
        handler (value) {
          if (!value) {
            return
          }
          if (value.users.length === 0 && value.groups.length === 0) {
            return;
          }
          if (JSON.stringify(value) == this.lastEmitted) {
            return;
          }
          this.loading = true;
          let results = [];

          let usersPromise = Promise.all(
            value.users.map(item => {
              if (typeof item == 'number' || typeof item == 'string') {
                return ProcessMaker.apiClient.get("users/" + item);
              } else {
                if (item.assignee) {
                  let id = item.assignee;
                  return ProcessMaker.apiClient.get("users/" + id);
                }
              }
            })
          )
            .then(items => {
              items.forEach(item => {
                results.push(this.addUsernameToFullName(item.data));
              });
            });

          let groupsPromise = Promise.all(
            value.groups.map(item => {
              if (typeof item == 'number' || typeof item == 'string' ) {
                return ProcessMaker.apiClient.get("groups/" + item);
              } else {
                if (item.assignee) {
                  let id = this.unformatGroup(item.assignee);
                  return ProcessMaker.apiClient.get("groups/" + id);
                }
              }
            })
          )
            .then(items => {
              items.forEach(item => {
                results.push(this.formatGroup(item.data));
              });
            });

          Promise.all([usersPromise, groupsPromise])
            .then(() => {
              this.content = results;
              this.loading = false;
            });
        }
      }
    },
    methods: {
      updateSeletected() {
        this.lastEmitted = JSON.stringify(this.selected);
        this.$emit("input", this.selected);
      },
      addUsernameToFullName(user) {
        if (!user.fullname || ! user.username)
        {
          return user;
        }
        let status = '';
        if (user.status === 'INACTIVE') {
          status = " - " + this.$t('Inactive');
        }
        return {...user, fullname: `${user.fullname} (${user.username}${status})`};
      },
      load (filter) {
        this.options = [];
        if (!this.hideUsers) {
          this.loadUsers(filter);
        }
        if (!this.hideGroups) {
          this.loadGroups(filter);
        }
      },
      loadUsers (filter) {
        ProcessMaker.apiClient
          .get("users" + (typeof filter === "string" ? "?filter=" + filter : ""))
          .then(response => {
            const users = response.data.data.map(user => this.addUsernameToFullName(user));
            this.users = users;

            if (response.data.data) {
              this.options.push({
                "type": this.labelUsers,
                "items": users,
              });
            }
          });
      },
      loadGroups (filter) {
        ProcessMaker.apiClient
          .get("groups" + (typeof filter === "string" ? "?filter=" + filter : ""))
          .then(response => {
            let groups = response.data.data.map(item => {
              return this.formatGroup(item);
            });

            if (groups) {
              this.options.push({
                "type": this.labelGroups,
                "items": groups
              });
            }
          });
      },
      formatGroup (item) {
        if (item && typeof item.id == 'number') {
          item.id = "group-" + item.id;
        }
        item.fullname = item.name;
        if (item.status === 'INACTIVE') {
          item.fullname += " (" + this.$t('Inactive') + ")";
        }
        return item;
      },
      unformatGroup(groupId) {
        if (typeof groupId == 'number') {
          return groupId;
        } else {
          let id = groupId.replace('group-', "");
          return id;
        }
        
      }
    },
  };
</script>
